package com.travelsky.server.chat_socket;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 代码提交工具-服务器端 与客户端连接的线程类
 ******************************************
 * @author HuangFeng  [2017年7月5日 下午12:50:09]
 * @version 1.0
 ******************************************
 */
public class ClientThread extends Thread {

	private Server server;//服务器对象
	private ServerThread serverThread;
	private Socket clientSocket; // 客户端套接字
	private boolean flag_exit = false;
	private long lastSendTime; //最后一次发送数据的时间  
	public DataOutputStream dos;
	public DataInputStream dis;
	public ObjectInputStream ois;
	public ObjectOutputStream oos;

	public ClientThread() {}

	/**
	 * 构造方法
	 ******************************************
	 * @author HuangFeng [2017年10月29日 上午12:53:57]
	 * @version 1.0
	 ******************************************
	 * @param socket 客户端套接字
	 * @param server 服务器对象
	 */
	public ClientThread(Socket socket, Server server) {
		this.clientSocket = socket;
		this.server = server;
		try {
			dis = new DataInputStream(clientSocket.getInputStream());
			dos = new DataOutputStream(clientSocket.getOutputStream());
			ois = new ObjectInputStream(new BufferedInputStream(clientSocket.getInputStream()));  
			oos = new ObjectOutputStream(clientSocket.getOutputStream());
            oos.writeObject(server.projectGroups);
		} catch (IOException e) {
			closeClienthread();
		}
	}

	@Override
	public void run() {
		while (flag_exit) {
			try {
				// 客户端十秒没有发心跳就断开连接
				if (lastSendTime > 0 && System.currentTimeMillis() - lastSendTime > 10000) {
					// 还未连接到项目组
					if (this.serverThread == null) {
						closeClienthread();
					} else {
						List<ClientThread> lostConnection = new ArrayList<ClientThread>();
						lostConnection.add(this);
						this.serverThread.clearLostConnection(lostConnection);
					}
					continue;
				}
				// 睡眠一会，减少CPU占用率
				sleep(500);
				String Message = dis.readUTF();
				if (Message == null || Message.isEmpty()) {
					continue;
				}
				if (Message.equals("heartpackage")) {
					lastSendTime = System.currentTimeMillis();
					continue;
				} else if (Message.contains("@updateVersion")) {
					String[] info = Message.split("@updateVersion");
					// 如果服务器版本跟本地版本不一致
					if (!server.version.equals(info[0])) {
						sendClientFile();
					}
					Message = "";
				} else if (Message.contains("@login")) {
					String[] info = Message.split("@login");
					String groupName = info[0];
					String username = info[1];
					server.login(groupName, username, this);
					Message = "";
				} else if (Message.contains("@exit")) {
					String[] userInfo = Message.split("@exit");
					int userID = Integer.parseInt(userInfo[1]);
					serverThread.users.remove(userID);
					serverThread.clients.removeElement(this);
					closeClienthread();
					Message = serverThread.getUserList();
				} else if (Message.contains("@lockToken")) {
					// 当前没有人锁定
					if (serverThread.lockTokenUser.equals("0")) {
						String[] chat = Message.split("@lockToken");
						serverThread.removeWaitQueue(chat[0]);
						serverThread.lockTokenUser = chat[0];
						StringBuffer sb = new StringBuffer();
						SimpleDateFormat form = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
						String date = form.format(new Date());
						sb.append(chat[0] + "  " + date + "\n");
						sb.append("已锁定令牌" + "@chat" + "@lockToken" + serverThread.lockTokenUser);
						Message = new String(sb);
					} else {
						Message = "";
					}
				} else if (Message.contains("@releaseToken")) {
					String[] chat = Message.split("@releaseToken");
					if (chat[0].contains("@chat")) {
						chat[0] = serverThread.lockTokenUser;
					}
					serverThread.lockTokenUser = "0";
					StringBuffer sb = new StringBuffer();
					SimpleDateFormat form = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
					String date = form.format(new Date());
					sb.append(chat[0] + "  " + date + "\n");
					sb.append("已释放令牌" + "@chat" + "@releaseToken" + serverThread.lockTokenUser);
					Message = new String(sb);
				} else if (Message.contains("@waitToken")) {
					String[] userInfo = Message.split("@waitToken");
					serverThread.addWaitQueue(userInfo[0]);
					StringBuffer sb = new StringBuffer();
					for (String string : serverThread.waitQueue) {
						sb.append(string + ",");
					}
					sb.append("@queue");
					Message = new String(sb);
				} else if (Message.contains("@canelWaitToken")) {
					String[] userInfo = Message.split("@canelWaitToken");
					serverThread.removeWaitQueue(userInfo[0]);
					StringBuffer sb = new StringBuffer();
					for (String string : serverThread.waitQueue) {
						sb.append(string + ",");
					}
					sb.append("@queue");
					Message = new String(sb);
				} else if (Message.contains("@chat")) {
					String[] chat = Message.split("@chat");
					StringBuffer sb = new StringBuffer();
					SimpleDateFormat form = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
					String date = form.format(new Date());
					sb.append(chat[0] + "  " + date + "\n");
					sb.append(chat[1] + "@chat");
					Message = new String(sb);
				}
				if (Message != null && !Message.isEmpty()) {
					serverThread.messages.addElement(Message);
				}
			} catch (Exception e) {
				// e.printStackTrace();
			}
		}
	}

	/**
	 * 发送最新客户端文件
	 ******************************************
	 * @author HuangFeng [2017年8月24日 上午10:41:23]
	 * @version 1.0
	 ******************************************
	 */
	private void sendClientFile() {
		try{
			dos.writeUTF(server.updateMessage);
			dos.flush();
			clientSocket.setSoTimeout(0);
			String message = dis.readUTF();
			if(message == null || !message.equals("begin")){
				closeClienthread();
				return;
			}
			String filePath = "/root/代码提交工具"+server.version+".exe";
			//String filePath = "C:/Users/HuangFeng/Desktop/新建文件夹/代码提交工具V1.4.4.exe";
			File file = new File(filePath);
			DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
			dos.writeUTF(file.getName());
			dos.flush();
			int bufferSize = 8192;
			byte[] buf = new byte[bufferSize];
			while(true){
				int read = 0 ;
				if (fis != null){
					read = fis.read(buf);
					// 从包含的输入流中读取一定数量的字节，并将它们存储到缓冲区数组 byte
	                // 以整数形式返回实际读取的字节数。在输入数据可用、检测到文件末尾 (end of file)  
	                // 或抛出异常之前，此方法将一直阻塞。 
				}
				if(read == -1){
					break;
				}
				dos.write(buf, 0, read);
			}
			dos.flush();
			fis.close();
			closeClienthread();
		}catch(Exception e){
			e.printStackTrace();
			closeClienthread();
		}
 	}

	/**
	 * 关闭此线程
	 ******************************************
	 * @author HuangFeng [2017年7月5日 下午12:51:32]
	 * @version 1.0
	 ******************************************
	 */
	public void closeClienthread() {
		try {
			if (clientSocket != null) {
				dis.close();
				dos.close();
				ois.close();
				oos.close();
				clientSocket.close();
			}
			if(serverThread != null && serverThread.clients.size() == 0){
				serverThread.stopServerThread();
			}
		}catch (IOException e) {
			e.printStackTrace();
		}
		setFlag_exit(false);
	}

	/**
	 * 设置退出标志
	 ******************************************
	 * @author HuangFeng [2017年10月27日 上午9:42:51]
	 * @version 1.0
	 ******************************************
	 * @param b
	 */
	public void setFlag_exit(boolean b) {
		flag_exit = b;
	}

	/**
	 * 获取 serverThread
	 * @return the serverThread
	 */
	public ServerThread getServerThread() {
		return serverThread;
	}

	/**
	 * 设置 serverThread
	 * @param serverThread the serverThread to set
	 */
	public void setServerThread(ServerThread serverThread) {
		this.serverThread = serverThread;
	}

}
